<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8"/>
    <meta name="Keywords" content=""/>
    <meta name="Description" content=""/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
    <meta name="viewport"
          content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=2,user-scalable=yes,minimal-ui"/>
    <meta name="apple-mobile-web-app-capable" content="yes"/>
    <title>3D</title>
    <style>
        html, body {
            height: 100%;
            margin: 0;
            padding: 0;
        }
    </style>
    <script src="ball3d.js"></script>
</head>
<body>
<canvas></canvas>
<script>
    //<![CDATA[
    var run = window.requestAnimationFrame || window.webkitRequestAnimationFrame || function (cb) {
                        return setTimeout(cb, 16.6)
                    },
            W = document.body.clientWidth,
            H = document.body.clientHeight,
            cvs = document.querySelector("canvas"),
            g = cvs.getContext("2d"),
            balls = [],
            numBalls = 15,
            fl = 250,
            vpX = W / 2,
            vpY = H / 2,
            angleX = 0,
            angleY = 0;
    cvs.width = W;
    cvs.height = H;

    for (var ball, i = 0; i < numBalls; i++) {
        ball = new Ball3d(5, "#000000");
        ball.xpos = Math.random() * 200 - 100;
        ball.ypos = Math.random() * 200 - 100;
        ball.zpos = Math.random() * 200 - 100;
        balls.push(ball);
    }

    function rotate(ball, angleX, angleY) {
        var cX = Math.cos(angleX),
                sX = Math.sin(angleX),
                cY = Math.cos(angleY),
                sY = Math.sin(angleY),
                x1 = cY * ball.xpos - sY * ball.zpos,
                z1 = cY * ball.zpos + sY * ball.xpos,
                y1 = cX * ball.ypos - sX * z1;
        z1 = cX * z1 + sX * ball.ypos;

        ball.xpos = x1;
        ball.ypos = y1;
        ball.zpos = z1;
    }

    function setPerspective(ball) {
        if (ball.zpos > -fl) {
            var scale = fl / (fl + ball.zpos);
            ball.scaleX = ball.scaleY = scale;
            ball.x = vpX + ball.xpos * scale;
            ball.y = vpY + ball.ypos * scale;
            ball.visible = true;
        }
        else {
            ball.visible = false;
        }
    }

    function move(ball, i) {
        rotate(ball, angleX, angleY);
        setPerspective(ball);
        if (i === 0) {
            g.moveTo(balls[i].x, balls[i].y);
        }
        else {
            g.lineTo(balls[i].x, balls[i].y);
        }
    }

    function draw(ball) {
        if (ball.visible) {
            ball.draw(g);
        }
    }

    cvs.addEventListener("mousemove", function (e) {
        var crd = document.body.getBoundingClientRect();
        angleY = Math.max(-0.1, Math.min(0.1, (e.clientX - crd.left - vpX) * 0.001));
        angleX = Math.max(-0.1, Math.min(0.1, (e.clientY - crd.top - vpY) * 0.001));
    }, false);

    (function drawFrame() {
        g.clearRect(0, 0, W, H);
        balls.forEach(move);
        g.stroke();
        balls.forEach(draw);

        run(drawFrame);
    })();
    //]]>
</script>
</body>
</html>
